﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace ExcelUnity.Core
{
    public class CsvHelper
    {
        public static CsvSheet CreateCsvSheet(Stream stream)
        {
            using var streamReader = new StreamReader(stream, false);
            var text = streamReader.ReadToEnd();

            var rows = text.Split(Environment.NewLine).ToList();

            var rowIndex = 0;
            var csvRows = rows.Select(x =>
            {
                var row = new CsvRow(rowIndex++, x);
                return row;
            }).ToList();
            return new CsvSheet(csvRows);
        }
    }

    public class CsvSheet
    {
        public CsvSheet(List<CsvRow> rows)
        {
            Rows = rows;
            FirstRowIndex = rows.FirstOrDefault(x => !x.IsEmpty())?.RowIndex ?? 0;
        }
        public List<CsvRow> Rows { get; set; }

        public int RowNum => Rows.Count;

        public CsvRow GetRow(int rowIndex)
        {
            return Rows.FirstOrDefault(x => x.RowIndex == rowIndex);
        }

        public int FirstRowIndex { get; }

        public void Write(Stream stream, Encoding? encoding = null)
        {
            using StreamWriter sw = new StreamWriter(stream, encoding ?? Encoding.UTF8);
            foreach (var item in Rows)
            {
                sw.WriteLine(item.SourceString);
            }
        }
    }

    public class CsvRow
    {
        public CsvRow(int rowIndex, string sourceStr)
        {
            RowIndex = rowIndex;
            SourceString = sourceStr;
            var cellIndex = 0;
            Cells = sourceStr.Split(",").Select(y => new CsvCell(cellIndex++, y)).ToList();
            FirstCellIndex = Cells.IsNullOrEmpty() ? 0 : Cells.Min(x => x.ColumnIndex);
            LastCellIndex = Cells.IsNullOrEmpty() ? 0 : Cells.Max(x => x.ColumnIndex);
        }

        public CsvRow(int rowIndex, int columnCount, IEnumerable<CsvCell> cells)
        {
            RowIndex = rowIndex;
            Cells = cells.ToList();
            FirstCellIndex = Cells.IsNullOrEmpty() ? 0 : Cells.Min(x => x.ColumnIndex);
            LastCellIndex = Cells.IsNullOrEmpty() ? 0 : Cells.Max(x => x.ColumnIndex);

            //从0开始，避免空单元格
            SourceString = string.Join(",", Enumerable.Range(0, columnCount).Select(x => GetCellValueOrEmpty(x)));
        }

        public int RowIndex { get; set; }

        public string SourceString { get; private set; }

        public List<CsvCell> Cells { get; }

        public int FirstCellIndex { get; }

        public int LastCellIndex { get; }

        public int CellCount => Cells.Count;

        public CsvCell GetCell(int index)
        {
            return Cells.First(x => x.ColumnIndex == index);
        }

        public string GetCellValueOrEmpty(int columnIndex)
        {
            return Cells.FirstOrDefault(x => x.ColumnIndex == columnIndex)?.Value ?? string.Empty;
        }

        public bool IsEmpty(int? startCellIndex = null, int? maxCellIndex = null)
        {
            var cellStartIndex = startCellIndex ?? FirstCellIndex;
            var cellEndIndex = maxCellIndex ?? LastCellIndex;

            for (int cellIndex = cellStartIndex; cellIndex <= cellEndIndex; cellIndex++)
            {
                if (GetCellValueOrEmpty(cellIndex).IsNotNullOrWhiteSpace())
                    return false;
            }
            return true;
        }

        public void AppendLastCell(string value)
        {
            Cells.Add(new CsvCell(CellCount, value));
            SourceString = $"{SourceString},{value}";
        }
    }

    public class CsvCell
    {
        public CsvCell(int index, string? value)
        {
            ColumnIndex = index;
            Value = value?.Trim() ?? string.Empty;
        }
        public int ColumnIndex { get; set; }

        public string Value { get; }
    }
}
